#include <stdlib.h>
#include "Arbre.h"
#include "Symbole.h"
#include "SymboleValue.h"
#include "NoeudVisitor.h"



NoeudVisitor::NoeudVisitor() { } //
NoeudVisitor::~NoeudVisitor() { } //
//    virtual ~NoeudVisitor();
void NoeudVisitor::VisitNoeudProg ( NoeudProg* )
{
}
void NoeudVisitor::VisitNoeudSeqInst ( NoeudSeqInst* )
{
}
void NoeudVisitor::VisitNoeudSeqDecl ( NoeudSeqDecl* )
{
}
void NoeudVisitor::VisitNoeudPour ( NoeudPour* )
{
}
void NoeudVisitor::VisitNoeudSi ( NoeudSi* )
{
}
void NoeudVisitor::VisitNoeudTantQue ( NoeudTantQue* )
{
}
void NoeudVisitor::VisitNoeudRepeter ( NoeudRepeter* )
{
}
void NoeudVisitor::VisitNoeudAffectation ( NoeudAffectation* )
{
}
void NoeudVisitor::VisitNoeudDeclaration ( NoeudDeclaration* )
{
}
void NoeudVisitor::VisitNoeudEcrire ( NoeudEcrire* )
{
}
void NoeudVisitor::VisitNoeudLire ( NoeudLire* )
{
}
void NoeudVisitor::VisitNoeudOperateurBinaire ( NoeudOperateurBinaire* )
{
}
void NoeudVisitor::VisitSymboleValue ( SymboleValue* )
{
}



AfficherVisitor::AfficherVisitor() : NoeudVisitor()
{
    indentation =0;    //
}
//    virtual ~NoeudVisitor();
void AfficherVisitor::VisitNoeudProg ( NoeudProg* )
{
    afficherIndentation();
    cout << "Le programme : " << endl;
}
void AfficherVisitor::VisitNoeudSeqInst ( NoeudSeqInst* e )
{
    afficherIndentation();
    cout << "Noeud - Sequence de " << e->getSize() << " instruction(s)" << endl;
}
void AfficherVisitor::VisitNoeudSeqDecl ( NoeudSeqDecl* e )
{
    afficherIndentation();
    cout << "Noeud - Sequence de " << e->getSize() << " declaration(s)" << endl;
}
void AfficherVisitor::VisitNoeudPour ( NoeudPour* )
{
    afficherIndentation();
    cout << "Noeud - Pour" << endl;
}
void AfficherVisitor::VisitNoeudSi ( NoeudSi* )
{
    afficherIndentation();
    cout << "Noeud - Si" << endl;
}
void AfficherVisitor::VisitNoeudTantQue ( NoeudTantQue* )
{
    afficherIndentation();
    cout << "Noeud - TantQue" << endl;
}
void AfficherVisitor::VisitNoeudRepeter ( NoeudRepeter* )
{
    afficherIndentation();
    cout << "Noeud - Repeter" << endl;
}
void AfficherVisitor::VisitNoeudAffectation ( NoeudAffectation* )
{
    afficherIndentation();
    cout << "Noeud - Affectation" << endl;
}
void AfficherVisitor::VisitNoeudDeclaration ( NoeudDeclaration* e )
{
    afficherIndentation();
    cout << "Noeud - Declaration \"" << e->getType().getChaine() << "\" : " << endl;
}
void AfficherVisitor::VisitNoeudEcrire ( NoeudEcrire* )
{
    afficherIndentation();
    cout << "Noeud - Ecrire" << endl;
}
void AfficherVisitor::VisitNoeudLire ( NoeudLire* )
{
    afficherIndentation();
    cout << "Noeud - Lire" << endl;
}
void AfficherVisitor::VisitNoeudOperateurBinaire ( NoeudOperateurBinaire* e )
{
    afficherIndentation();
    cout << "Noeud - Operateur Binaire \"" << e->getOperateur().getChaine() << "\" applique a : " << endl;
}
void AfficherVisitor::VisitSymboleValue ( SymboleValue* e )
{
    afficherIndentation();
    cout << "Feuille - Symbole value : " << e->getChaine() << endl;
}




TypeVisitor::TypeVisitor() : NoeudVisitor()
{

}
//virtual ~NoeudVisitor();
void TypeVisitor::VisitNoeudProg ( NoeudProg* )
{
}
void TypeVisitor::VisitNoeudSeqInst ( NoeudSeqInst* )
{
//     cout << " verif type seqinst " << endl;
}
void TypeVisitor::VisitNoeudSeqDecl ( NoeudSeqDecl* )
{
//     cout << " verif type seqinst " << endl;
}
void TypeVisitor::VisitNoeudPour ( NoeudPour* )
{
//     cout << " verif type seqpour " << endl;
}
void TypeVisitor::VisitNoeudSi ( NoeudSi* )
{
//     cout << " verif type seqsi " << endl;
}
void TypeVisitor::VisitNoeudTantQue ( NoeudTantQue* )
{
//     cout << " verif type seqtantque " << endl;
}
void TypeVisitor::VisitNoeudRepeter ( NoeudRepeter* )
{
//     cout << " verif type seqrepeter " << endl;
}
void TypeVisitor::VisitNoeudAffectation ( NoeudAffectation* e )
{
/*	  cout << " Erreur de typage , float variable :  " << typeid (*e->getExpression()->getValeur()).name()  << endl;
	  cout << " Erreur de typage , float ValeurFloat :  " << typeid ( ValeurInt ).name() << endl;*/
//    cout << " verif type affectation putin" << endl;
    if ( ( ((SymboleValue*)e->getVariable())->SymboleValue::getType() == "entier" ) && ( typeid (*e->getExpression()->getValeur() ) != typeid ( ValeurInt ) ) )
    {
	cout << " Erreur de typage (ligne  " << ((SymboleValue*)e->getVariable())->getLigne() << ") \"" << ((SymboleValue*)e->getVariable())->Symbole::getChaine() << "\" demande un Entier" << endl;
        exit ( -1 );
    }
    if ( (( (SymboleValue*)e->getVariable())->SymboleValue::getType() == "reel" ) && ( typeid ( *e->getExpression()->getValeur() ) != typeid ( ValeurFloat ) ) )
    {
	cout << " Erreur de typage : (ligne  " << ((SymboleValue*)e->getVariable())->getLigne() << ") \"" << ((SymboleValue*)e->getVariable())->Symbole::getChaine() << "\" demande un Reel" << endl;
        exit ( -1 );
    }
    if ( (( (SymboleValue*)e->getVariable())->SymboleValue::getType() == "chaine" ) && ( typeid ( *e->getExpression()->getValeur() ) != typeid ( ValeurString ) ) )
    {
	cout << " Erreur de typage : (ligne  " << ((SymboleValue*)e->getVariable())->getLigne() << ") \"" << ((SymboleValue*)e->getVariable())->Symbole::getChaine() << "\" demande une Chaine" << endl;
        exit ( -1 );
    }
    if ( (( (SymboleValue*)e->getVariable())->SymboleValue::getType() == "chara" ) && ( typeid ( *e->getExpression()->getValeur() ) != typeid ( ValeurString ) ) )
    {
	cout << " Erreur de typage : (ligne  " << ((SymboleValue*)e->getVariable())->getLigne() << ") \"" << ((SymboleValue*)e->getVariable())->Symbole::getChaine() << "\" demande une Charactere" << endl;
        exit ( -1 );
    }
//       if ( ( typeid ( e->getVariable()->getValeur() ) != typeid ( ValeurFloat ) ) ) // && ( typeid ( e->getExpression()->getValeur() ) != typeid ( ValeurFloat* ) )
//       {
// // 		  cout << " Erreur de typage , float exp :  " << typeid ( *e->getExpression()->getValeur() ).name() << endl;
// // 	  cout << " Erreur de typage , float variable :  " << ((SymboleValue*)e->getVariable())->SymboleValue::getType()  << endl;
// // 	  cout << " Erreur de typage , float ValeurFloat :  " << typeid ( ValeurFloat ).name() << endl;
// // 	  cout << " Erreur de typage , float ValeurINT :  " << typeid ( Valeur ).name() << endl;
// // 	  cout << " Erreur de typage , float ValeurSTRNG :  " << typeid ( ValeurString ).name() << endl;
// // //	  cout << " Erreur de typage , float Valeurchara :  " << typeid ( Valeurc ).name() << endl;
// // 
// // 	  cout << " Erreur de typage , float exp :  " << typeid ( e->getExpression()->getValeur() ).name() << endl;
// 	//  exit ( -1 );
//       }
}
void TypeVisitor::VisitNoeudDeclaration ( NoeudDeclaration* )
{
//     cout << " verif type declaration " << endl;
}
void TypeVisitor::VisitNoeudEcrire ( NoeudEcrire* )
{

}
void TypeVisitor::VisitNoeudLire ( NoeudLire* )
{


}
void TypeVisitor::VisitNoeudOperateurBinaire ( NoeudOperateurBinaire* e )
{
//     if (e->operator = "+")
//         if (typeid(var->getValeur()) == typeid(exp->getValeur())
//             }
//
  //  cout << " verif type operation bin " << endl;
    if ( ( e->getOperateur() == "+" ) || ( e->getOperateur() == "-" )  || ( e->getOperateur() == "*" )  || ( e->getOperateur() == "/" ) )
    {
        if ( ( typeid ( *e->getOperandeGauche()->getValeur() ) == typeid ( ValeurInt ) ) && ( typeid (*e->getOperandeDroit()->getValeur() ) != typeid ( ValeurInt ) ) )
        {
            cout << " Erreur de typage , int " << endl;
            exit ( -1 );
        }
        else if ( ( typeid (*e->getOperandeGauche()->getValeur() ) == typeid ( ValeurFloat ) ) && ( typeid ( *e->getOperandeDroit()->getValeur() ) != typeid ( ValeurFloat ) ) )
        {
            cout << " Erreur de typage , float " << endl;
            exit ( -1 );
        }
        if ( ( typeid (*e->getOperandeGauche()->getValeur() ) == typeid ( ValeurString ) ) || ( typeid (*e->getOperandeDroit()->getValeur() ) == typeid ( ValeurString ) ) )
        {
            cout << " Erreur de typage , +,-,*,/ seulement sur int ou float " << endl;
            exit ( -1 );
        }
    }
    if ( ( e->getOperateur() == "et" ) || ( e->getOperateur() == "ou" ) )
    {
        if ( ( typeid ( *e->getOperandeGauche()->getValeur() ) == typeid ( ValeurString ) ) || ( typeid (*e->getOperandeDroit()->getValeur() ) == typeid ( ValeurString ) ) )
        {
            cout << " Boolean : int ou float " << endl;
            exit ( -1 );
        }
    }
    if ( ( e->getOperateur() == "==" ) || ( e->getOperateur() == "!=" ) || ( e->getOperateur() == "<=" )
    		|| ( e->getOperateur() == "<" ) || ( e->getOperateur() == ">=" ) || ( e->getOperateur() == ">" ) )
    {
        if ( ( typeid ( *e->getOperandeGauche()->getValeur() ) == typeid ( ValeurInt ) ) && ( typeid (*e->getOperandeDroit()->getValeur() ) != typeid ( ValeurInt ) ) )
        {
            cout << " Erreur de typage , int comparaison avec autre" << endl;
            exit ( -1 );
        }
        else if ( ( typeid (*e->getOperandeGauche()->getValeur() ) == typeid ( ValeurFloat ) ) && ( typeid ( *e->getOperandeDroit()->getValeur() ) != typeid ( ValeurFloat ) ) )
        {
            cout << " Erreur de typage , float comparaison avec autre" << endl;
            exit ( -1 );
        }
        if ( ( typeid (*e->getOperandeGauche()->getValeur() ) == typeid ( ValeurString ) ) || ( typeid (*e->getOperandeDroit()->getValeur() ) == typeid ( ValeurString ) ) )
        {
            cout << " Erreur de typage , string comparaison avec autre" << endl;
            exit ( -1 );
        }
    }
}
void TypeVisitor::VisitSymboleValue ( SymboleValue* )
{

}


// ////////////////////////////////////////////////////////////////////////////////
// void TypeVisitor::erreur ( string mess )
// {
//     cout << endl << "-------- Erreur de Typage " << ls.getLigne() << " - Colonne "
//          << ls.getColonne() << endl << "   Attendu : " << mess << endl
//          << "   Trouve  : " << ls.getSymCour() << endl << endl;
//     exit ( 0 ); // plus tard, on levera une exception
// }
